#include <math.h>
#include "arco.h"

Arco::Arco()
{
    //ctor
}

Arco::~Arco()
{
    //dtor
}

gboolean Arco::intersect(gdouble x, gdouble y)
{
    const gdouble distanza_massima = 2.0;
    gdouble start_x; 
    gdouble start_y;
    gdouble end_x;
    gdouble end_y;
    
    calcola_nuovi_inizio_fine(start_x, start_y, end_x, end_y);
 
    if(x > min(start_x, end_x) && x < max(start_x, end_x) &&
       y > min(start_y, end_y) && y < max(start_y, end_y))
    {
        gdouble m = (end_y - start_y) / (end_x - start_x);
        gdouble q = start_y - m * start_x;
        
        gdouble distanza = (y - m*x - q) / (sqrt(1 + pow(m, 2)));
        
        return (distanza >= -distanza_massima && distanza <= distanza_massima);  
    }
    
    return FALSE;
}

void Arco::calcola_vertici_freccia(double start_x, double start_y, double end_x, double end_y, double& x1, double& y1, double& x2, double& y2)
{
    gdouble angolo = atan2 (end_y - start_y, end_x - start_x) + G_PI;
    const gdouble angolo_freccia = 0.5;
    const gdouble lunghezza_freccia = 15.0;

    x1 = end_x + lunghezza_freccia * cos(angolo - angolo_freccia);
    y1 = end_y + lunghezza_freccia * sin(angolo - angolo_freccia);
    x2 = end_x + lunghezza_freccia * cos(angolo + angolo_freccia);
    y2 = end_y + lunghezza_freccia * sin(angolo + angolo_freccia);
}

void Arco::calcola_nuovi_inizio_fine(gdouble &start_x, gdouble &start_y, gdouble &end_x, gdouble &end_y)
{
    gdouble alpha = atan2(destinazione->get_y() - origine->get_y(), destinazione->get_x() - origine->get_x());
    
    start_x = origine->get_x();
    start_y = origine->get_y();
    end_x = destinazione->get_x();
    end_y = destinazione->get_y();
    
    gdouble delta_x = cos(alpha) * origine->get_raggio();
    gdouble delta_y = sin(alpha) * origine->get_raggio();
    
    start_x += delta_x;
    start_y += delta_y;
    end_x -= delta_x;
    end_y -= delta_y;
}

gboolean Arco::is_minimo()
{
    if(destinazione->get_precedente() != NULL)
        return destinazione->get_precedente()->get_indice() == origine->get_indice();
    return false;
}

void Arco::draw(cairo_t* &cr)
{
    const guint FONT_SIZE = 16;
    
    if(get_destinazione() != NULL)
    {
        if(is_over())
        {
            cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
            cairo_set_line_width(cr, 3.0);
        }
        else if(is_minimo())
        {
            cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
            cairo_set_line_width(cr, 3.0);
        } else
        {
            cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
            cairo_set_line_width(cr, 0.5);        
        }
        
        gdouble start_x; 
        gdouble start_y;
        gdouble end_x;
        gdouble end_y;
        
        calcola_nuovi_inizio_fine(start_x, start_y, end_x, end_y);
        
        cairo_move_to(cr, start_x, start_y);
        cairo_line_to(cr, end_x, end_y);
        cairo_stroke(cr);
        
        // Disegna la punta
        gdouble x1;
        gdouble y1;
        gdouble x2;
        gdouble y2;

        calcola_vertici_freccia(start_x, start_y, end_x, end_y, x1, y1, x2, y2);

        cairo_move_to(cr, end_x, end_y);
        cairo_line_to (cr, x1, y1);
        cairo_line_to (cr, x2, y2);
        cairo_close_path(cr);

        cairo_stroke_preserve(cr);

        cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
        cairo_fill(cr);        
        
        // Scrive la lunghezza
        gdouble x_medio = (end_x + start_x)/2;
        gdouble y_medio = (end_y + start_y)/2;
        
        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
        
        cairo_select_font_face(cr, "Arial",
          CAIRO_FONT_SLANT_NORMAL,
          CAIRO_FONT_WEIGHT_BOLD);

        cairo_set_font_size(cr, FONT_SIZE);
        cairo_move_to(cr, x_medio, y_medio);
      
        char label[4];
        sprintf(label, "%d", get_lunghezza());
        cairo_show_text(cr, label);  
        cairo_stroke(cr);        
    }
}

void Arco::update(gdouble x, gdouble y)
{

}

